package com.feib.soeasy.action;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;


import com.feib.soeasy.job.util.UnicodeInputStream;
import com.feib.soeasy.model.ColumnDefinition;
import com.feib.soeasy.model.FormatDefinition;
import com.feib.soeasy.model.Group;
import com.feib.soeasy.model.LabelValue;
import com.feib.soeasy.model.Payment;
import com.feib.soeasy.model.UploadFile;
import com.feib.soeasy.pagination.PaginatedList;
import com.feib.soeasy.pagination.QryDownloadFileList;
import com.feib.soeasy.service.ColumnDefinitionService;
import com.feib.soeasy.service.FormatDefinitionService;
import com.feib.soeasy.service.GroupService;
import com.feib.soeasy.service.PaymentService;
import com.feib.soeasy.service.UploadFileService;
import com.feib.soeasy.util.CodeTableUtil;
import com.feib.soeasy.util.UserUtil;


import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.DontBind;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.LocalizableMessage;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.StreamingResolution;
import net.sourceforge.stripes.integration.spring.SpringBean;
import net.sourceforge.stripes.validation.DateTypeConverter;
import net.sourceforge.stripes.validation.LocalizableError;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import net.sourceforge.stripes.validation.ValidationErrorHandler;
import net.sourceforge.stripes.validation.ValidationErrors;

/**
 * @title (#)Soez1018ActionBean.java <br>
 * @description 帳單明細資料下載 Controller<br>
 * @author Leo Lee
 * @version 1.0.0 2010/12/16
 * @copyright Far Eastern International Bank Copyright (c) 2010<br>
 * @2010/12/16 create by Leo Lee<br>
 */
public class Soez1018ActionBean extends BaseActionBean implements ValidationErrorHandler {

    /**
     * 帳單明細資料下載作業畫面
     */
    private static final String DEFAULT_JSP = "/WEB-INF/views/soez1018/soez1018.jsp";

    /**
     * 帳單明細資料下載清單畫面
     */
    private static final String PAYMENT_LIST_JSP = "/WEB-INF/views/soez1018/soez1018List.jsp";
    /**
     * 檔案內容
     */
    private static final String AJAX_QUERY_PAYMENT_JSP = "/WEB-INF/views/soez1018/paymentList.jsp";
    /**
     * 業者代號查詢畫面
     */
    private static final String AJAX_QUERY_GROUP_JSP = "/WEB-INF/views/soez1018/groupPopUpList.jsp";

    /**
     * [業者代號]改變後觸發重製[收款類別]選項結果
     */
    private static final String AJAX_FORMT_DEF_OPTIONS_JSP = "/WEB-INF/views/soez1018/formatDefinitionOptions.jsp";

    /**
     * 帳單業者查詢條件
     */
    private Group qryGroup;

    private Group group;

    private Long uploadFilePk;

    private Integer qryPaymentStatus;

    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss");
    private SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMMdd");
    private SimpleDateFormat hhmmss = new SimpleDateFormat("hhmmss");

    /**
     * 帳單業者查詢結果
     */
    private PaginatedList<Group> queryGroupResult;


    /**
     * 查詢條件
     */
    @ValidateNestedProperties({
        @Validate(field="uploadFilePk", required=true, on={"doAjaxQueryFilePayments"}  )        
        , @Validate(field="group.groupNo", required=true, on={"doAjaxQuery"})
        , @Validate(field="uploadDate", converter=DateTypeConverter.class )
    })
    private UploadFile qryUploadFile;

    /** 
     * 查詢條件-上傳日期起
     */
    @Validate( required=true, on={"doAjaxQuery"}, converter=DateTypeConverter.class)
    private Date qryUploadFrom;

    /**
     * 查詢條件-上傳日期迄
     */
    @Validate( required=true, on={"doAjaxQuery"}, converter=DateTypeConverter.class)
    private Date qryUploadTo;

    @SpringBean("uploadFileService")
    private UploadFileService uploadFileService;

    /**
     * 查詢結果
     */
    private List<QryDownloadFileList> queryResult;

    /**
     * 查詢單筆Payment
     */
    private Payment resultPayment;

    /**
     * 收款類別選單
     */
    private List<LabelValue> formatDefinitionoOptions;

    @SpringBean("groupService")
    private GroupService groupService;

    @SpringBean("formatDefinitionService")
    private FormatDefinitionService formatDefinitionService;

    @SpringBean("fileImportDestination")
    private String fileImportDestination;

    @SpringBean("columnDefinitionService")
    private ColumnDefinitionService columnDefinitionService;

    /**
     * 檔案帳單明細查詢結果
     */
    private PaginatedList<Payment> queryPaymentResult;


    @SpringBean("paymentService")
    private PaymentService paymentService;

    @DontBind
    @DefaultHandler
    public Resolution doDefault()
    {
        logger.debug("Enter doDefault mehtod.");
        try {
            Calendar cal = Calendar.getInstance();
            qryUploadTo = cal.getTime();
            cal.add(Calendar.MONTH, -1);
            qryUploadFrom = cal.getTime();
        }
        catch (Exception e) {
        }

        return new ForwardResolution(DEFAULT_JSP); 
    }

    /**
     * 查詢
     * @return
     */
    public Resolution doAjaxQuery()
    {
        logger.debug("Enter doAjaxQuery mehtod.");
        try {

            //如果不是銀行端，則查詢條件要加入帳單業者限制
            if (!UserUtil.isBankGroup())
            {
                Group group = new Group();
                group.setGroupPk(UserUtil.getUserGroup().getGroupPk());
                qryUploadFile.setGroup(group);
            }            

            //呼叫服務查詢
            queryResult = uploadFileService.queryDownloadDetailFile(
                            qryUploadFile, qryUploadFrom, qryUploadTo, qryPaymentStatus);

            if(queryResult != null && queryResult.size() == 0 )
            {
                queryResult = null;
            }

        }
        catch (Exception e) {
            logger.error("帳單明細資料下載查詢錯誤(Soez1018ActionBean.doAjaxQuery):", e);

            // 轉換錯誤訊息
            ValidationErrors errors = new ValidationErrors();
            errors.addGlobalError(new LocalizableError("doAjaxQuery.exception") );
            getContext().setValidationErrors(errors);
            // 回傳 錯誤 HTML fragments
            return super.errorsToHtmlStreams(errors);
        }

        return new ForwardResolution(PAYMENT_LIST_JSP);
    }

    /**
     * 查詢轉入的帳單資料
     * @return
     */
    public Resolution doAjaxQueryFilePayments()
    {
        logger.debug("Enter doAjaxQueryFilePayments mehtod.");
        try {
            // 設定查詢條件
            Payment payment = new Payment();
            //payment.setGroup(qryUploadFile.getUploadGroup());
            UploadFile uploadFile = new UploadFile();

            uploadFile.setUploadFilePk(qryUploadFile.getUploadFilePk());
            payment.setUploadFile(uploadFile);
            payment.setPaymentStatus(qryPaymentStatus);
            //呼叫服務查詢
            queryPaymentResult = paymentService.queryByPayment(payment, null, null, queryPaymentResult);
        }
        catch (Exception e) {
            logger.error("帳單明細資料下載-帳單內容查詢錯誤(Soez1018ActionBean.doAjaxQueryFilePayments):", e);

            // 轉換錯誤訊息
            ValidationErrors errors = new ValidationErrors();
            errors.addGlobalError(new LocalizableError("doAjaxQuery.exception") );
            getContext().setValidationErrors(errors);
            // 回傳 錯誤 HTML fragments
            return super.errorsToHtmlStreams(errors);
        }

        return new ForwardResolution(AJAX_QUERY_PAYMENT_JSP);
    }

    /**
     * 帳單業者查詢
     * @return
     */
    public Resolution doAjaxQueryGroups()
    {
        logger.debug("Enter doAjaxQueryGroups mehtod.");
        try {
            //如果不是銀行端，則查詢條件要加入帳單業者限制
            if (!UserUtil.isBankGroup())
            {
                throw new Exception("No Authority");
            }


            //USER未輸入查詢條件，所以查詢物件會是NULL(查詢物件不可為NULL)
            if (null == qryGroup)
                qryGroup = new Group();

            //呼叫服務查詢
            queryGroupResult = groupService.queryByGroupExcludeBank(qryGroup, queryGroupResult);
        }
        catch (Exception e) {
            logger.error("帳單明細資料下載-帳單業者查詢錯誤(Soez1018ActionBean.doAjaxQueryGroups):", e);

            // 轉換錯誤訊息
            ValidationErrors errors = new ValidationErrors();
            errors.addGlobalError(new LocalizableError("doAjaxQuery.exception") );
            getContext().setValidationErrors(errors);
            // 回傳 錯誤 HTML fragments
            return super.errorsToHtmlStreams(errors);
        }

        return new ForwardResolution(AJAX_QUERY_GROUP_JSP);
    }

    
    public Resolution doDownloadUploadFileForCsv()
    {
        logger.debug("Enter doDownloadUploadFileForExcel mehtod.");

        StreamingResolution streamingResolution = null;
        BufferedReader reader = null;
        FileOutputStream outputStream = null;
        try {
            UploadFile uploadFile = uploadFileService.getUploadFileByPk(uploadFilePk);
            List<Payment> payments = paymentService.queryPaymentForDetailDownload(uploadFile, qryPaymentStatus);
            List<ColumnDefinition> columnDefinitions =  columnDefinitionService.queryColumnDefinitions(uploadFile.getFormatDefinition());
                            
        
            /* 讀取原本上傳檔案 */
            FileInputStream fis = new FileInputStream(uploadFile.getFilePathOnServer());
            String charsetName = "MS950";
            UnicodeInputStream uin = new UnicodeInputStream(fis, charsetName);
            charsetName = uin.getEncoding(); // check and skip possible BOM bytes
            Charset charset = Charset.forName(charsetName);

            InputStreamReader isr;
            if (null == charsetName){
                isr = new InputStreamReader(uin);
            }
            else {
                isr = new InputStreamReader(uin, charsetName);
            }

            reader = new BufferedReader(isr);

          
            /* 先依據起始位置排序排序 */
            Collections.sort(columnDefinitions, new Comparator<ColumnDefinition>() {
                //jeff 未設定 beignindex跟EndIndex的項目排到最後
                @Override
                public int compare(ColumnDefinition o1, ColumnDefinition o2) {
                    if (null == o1.getBeginIndex() && null == o2.getBeginIndex())
                        return 1;
                    if (null != o1.getBeginIndex() && null == o2.getBeginIndex())
                        return 1;
                    if (null == o1.getBeginIndex() && null != o2.getBeginIndex())
                        return 1;
                                       
                    
                    return o1.getBeginIndex().compareTo(o2.getBeginIndex());
                }
            });
            

            /* 繳費帳號於檔案中的位置 */  
            int beginIndex = 0;
            int endIndex = 0;
            for(ColumnDefinition columnDefinition : columnDefinitions)
            {
                if ("virtualAccount".equalsIgnoreCase(columnDefinition.getColumnName()))
                {
                    beginIndex = columnDefinition.getBeginIndex();
                    endIndex = columnDefinition.getEndIndex();
                    break;
                }
            }
            
            /* */
            Map<Integer, Boolean> duplicatBeginIndx = new HashMap<Integer, Boolean>();
            List<ColumnDefinition> newColumnDefinitions = new ArrayList<ColumnDefinition>();           
            int lastE = columnDefinitions.get(0).getEndIndex().intValue();
            for(ColumnDefinition columnDefinition : columnDefinitions)
            {
                if (null != duplicatBeginIndx.get(columnDefinition.getBeginIndex()))
                    continue;
                else
                    duplicatBeginIndx.put(columnDefinition.getBeginIndex(), Boolean.TRUE);
                
                //jeff 跳過未設定 beignindex跟EndIndex的項目
                if (null == columnDefinition.getBeginIndex() ||null ==columnDefinition.getEndIndex() )                          
                    continue;
                
                int b = columnDefinition.getBeginIndex().intValue();
                int e = columnDefinition.getEndIndex().intValue();
                
                if (b > 1 && b > lastE  &&  b != (lastE + 1))
                {
                    ColumnDefinition newOne = new ColumnDefinition();
                    newOne.setBeginIndex(lastE + 1);
                    newOne.setEndIndex(b-1);
                    newColumnDefinitions.add(newOne); 
                    duplicatBeginIndx.put(newOne.getBeginIndex(), Boolean.TRUE);
                }
                
                newColumnDefinitions.add(columnDefinition);
                lastE = e;
            }

            
            /* free resource */
            duplicatBeginIndx.clear();
            duplicatBeginIndx = null;


            /* 建立下載檔案存放目錄 */
            String toDest = fileImportDestination + "/" + uploadFile.getGroup().getGroupNo()+ "/" + UserUtil.getUserId() + "/";            
            File toFile = new File(toDest);
            // 目錄不存在則建立目錄
            if (!toFile.exists())
            {
                try {
                    toFile.mkdirs();
                }
                catch (Exception e) {
                    //無法建立匯入目錄
                    throw new Exception(new LocalizableMessage("can.not.create.import.folder", toFile.getAbsolutePath()).getMessage(getContext().getLocale()), e);
                }
            }

            /* 下載檔名 */
            String fileName = UUID.randomUUID().toString();
            File file = new File(toDest + fileName);
            outputStream = new FileOutputStream(file);

            byte[] csvSeparator = ",".getBytes();
            String lineData = null;
            byte[] lineBytes;
            while((lineData = reader.readLine()) != null) {

                lineBytes = lineData.getBytes(charsetName);

                /* 由檔案的繳費帳號找出該筆Payment資料 */
                String virtualAccount = new String(new String(lineBytes, beginIndex-1, endIndex- beginIndex+1, charset).getBytes("UTF-8"),"UTF-8");
                virtualAccount = virtualAccount.trim();
                Payment payment = getPayment(payments, virtualAccount);
                
                if (null != payment)
                {
                    /* 原始資料 */
                    int b = 0;
                    int e = 0;
                    
                    for(ColumnDefinition columnDefinition : newColumnDefinitions)
                    {
                        
                        
                        b = columnDefinition.getBeginIndex().intValue();
                        e = columnDefinition.getEndIndex().intValue();                      
                        String value = new String(lineBytes, b-1, e - b+1, charset);
                        outputStream.write(value.getBytes(charset));
                        outputStream.write(csvSeparator);
                    }
                    
                    /* 繳費單狀態 */
                    outputStream.write(payment.getPaymentStatus().toString().getBytes());
                    outputStream.write(csvSeparator);
                    
                    String statusName = CodeTableUtil.getInstance().getCodeName(CodeTableUtil.CODE_KIND_PAYMENT_STATUS, payment.getPaymentStatus().toString());
                    outputStream.write(statusName.getBytes(charsetName));
                    outputStream.write(csvSeparator);
                    

                    /* 已繳款加入繳款日期時間, 繳款通路代碼, 繳款通路說明, 實際繳款金額(2011/09/07 YD)*/
                    if(payment.getPaymentStatus().equals(new Integer(5)))  
                    {
                        // 繳款日期時間
                        Date date = payment.getWriteOffPayment().getWriteOffDate();
                        if (null != date)
                        {
                            outputStream.write(yyyyMMdd.format(date).getBytes());// 繳款日期
                            outputStream.write(csvSeparator);
                            
                            outputStream.write(hhmmss.format(date).getBytes());// 繳款時間
                            outputStream.write(csvSeparator);
                        }
                        else
                        {
                            outputStream.write(csvSeparator);
                            outputStream.write(csvSeparator);
                        }
                        

                        // 繳款通路代碼
                        String channel = payment.getWriteOffPayment().getChannel();
                        if (null != channel)
                            outputStream.write(channel.getBytes(charsetName));
                        outputStream.write(csvSeparator);

                        // 繳款通路說明
                        channel = CodeTableUtil.getInstance().getCodeName(CodeTableUtil.CODE_KIND_CHANNEL, payment.getWriteOffPayment().getChannel());
                        if (null != channel)
                            outputStream.write(channel.getBytes(charsetName));
                        outputStream.write(csvSeparator);
                        
                        /* 增加實際繳款金額(2011/09/07 YD) */
                        if (payment.getRealPayAmount() == null){
                        	logger.error("{} 已繳款，但實繳金額為null..", virtualAccount);
                        	outputStream.write(csvSeparator);
                        }else{	
                            outputStream.write(objectToString(payment.getRealPayAmount()).getBytes(charsetName));
                        }    
                        
                        outputStream.write(csvSeparator);
                    }
                    else
                    {
                        outputStream.write(csvSeparator); // 繳款日期
                        outputStream.write(csvSeparator); // 繳款時間
                        outputStream.write(csvSeparator); // 繳款通路代碼
                        outputStream.write(csvSeparator); // 繳款通路說明
                    }
                    
                    outputStream.write("\r\n".getBytes());
                }
                
            }

            outputStream.flush();
            outputStream.close();
            outputStream = null;

            reader.close();
            reader = null;

            byte[] bytes = new byte[(int)file.length()];

            BufferedInputStream bufferedInputStream = 
                new BufferedInputStream(new FileInputStream(file)); 

            bufferedInputStream.read(bytes);

            ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
            inputStream.close();
            bufferedInputStream.close();

            /* 下載檔名 */
            
            String   fname= uploadFile.getFileName();
            
            int   sub  =fname.indexOf(".");
                    
            if(0 > sub){
                
                fileName = fname + "_R.csv"; 
                
            }else{
            
                 fileName = uploadFile.getFileName().substring(0, sub) + "_R.csv";  
          
            }
            
           
           
            String isoFileName = new String(fileName.getBytes(), "ISO8859-1");

            streamingResolution = new StreamingResolution( 
                            "application/csv",inputStream).setFilename(isoFileName); //application/vnd.ms-excel

        } 
        catch (Exception e) 
        {
            logger.error("帳單明細下載錯誤(Soez1018ActionBean.doDownloadUploadFileAction):", e);

            // 轉換錯誤訊息
            ValidationErrors errors = new ValidationErrors();
            errors.addGlobalError(new LocalizableError("doDownloadUploadFileAction.exception") );
            getContext().setValidationErrors(errors);
            // 回傳 錯誤 HTML fragments
            return super.errorsToHtmlStreams(errors);
        }
        finally
        {
            
            try {
                if (null != outputStream)
                    outputStream.close();
            }
            catch (IOException e) {
            }
            outputStream = null;
            
            try {
                if (null != reader)
                    reader.close();
            }
            catch (IOException e) {
            }
            reader = null;
        }

        return streamingResolution;
    }

    public Resolution doDownloadUploadFileAction()
    {
        logger.debug("Enter doDownloadUploadFileAction mehtod.");
        StreamingResolution streamingResolution = null;
        BufferedReader reader = null;
        FileOutputStream outputStream = null;
        try {
            UploadFile uploadFile = uploadFileService.getUploadFileByPk(uploadFilePk);
            List<Payment> payments = paymentService.queryPaymentForDetailDownload(uploadFile, qryPaymentStatus);
            List<ColumnDefinition> columnDefinitions =  columnDefinitionService.queryColumnDefinitions(uploadFile.getFormatDefinition());

            /* 讀取原本上傳檔案 */
            FileInputStream fis = new FileInputStream(uploadFile.getFilePathOnServer());
            String charsetName = "MS950";
            UnicodeInputStream uin = new UnicodeInputStream(fis, charsetName);
            charsetName = uin.getEncoding(); // check and skip possible BOM bytes
            Charset charset = Charset.forName(charsetName);

            InputStreamReader isr;
            if (null == charsetName){
                isr = new InputStreamReader(uin);
            }
            else {
                isr = new InputStreamReader(uin, charsetName);
            }

            reader = new BufferedReader(isr);
            


            /* 繳費帳號於檔案中的位置 */
            int beginIndex = 0;
            int endIndex = 0;
            for(ColumnDefinition columnDefinition : columnDefinitions)
            {
                if ("virtualAccount".equalsIgnoreCase(columnDefinition.getColumnName()))
                {
                    beginIndex = columnDefinition.getBeginIndex();
                    endIndex = columnDefinition.getEndIndex();
                    break;
                }
            }  
            
            logger.debug("virtualAccount.beginIndex={}   virtualAccount.endIndex={}", beginIndex, endIndex);


            /* 建立下載檔案存放目錄 */
            String toDest = fileImportDestination + "/" + uploadFile.getGroup().getGroupNo()+ "/" + UserUtil.getUserId() + "/";            
            File toFile = new File(toDest);
            // 目錄不存在則建立目錄
            if (!toFile.exists())
            {
                try {
                    toFile.mkdirs();
                }
                catch (Exception e) {
                    //無法建立匯入目錄
                    throw new Exception(new LocalizableMessage("can.not.create.import.folder", toFile.getAbsolutePath()).getMessage(getContext().getLocale()), e);
                }
            }

            /* 下載檔名 */
            String fileName = UUID.randomUUID().toString();
            File file = new File(toDest + fileName);
            logger.debug("下載檔名={}", file.getAbsolutePath());
            outputStream = new FileOutputStream(file);

            String lineData = null;
            byte[] lineBytes;
            while((lineData = reader.readLine()) != null) {
                
                logger.debug("原始檔=[{}]", lineData);

                lineBytes = lineData.getBytes(charsetName);

                /* 由檔案的繳費帳號找出該筆Payment資料 */
                String virtualAccount = new String(new String(lineBytes, beginIndex-1, endIndex- beginIndex+1, charset).getBytes("UTF-8"),"UTF-8");
                virtualAccount = virtualAccount.trim();
                Payment payment = getPayment(payments, virtualAccount);

                if (null != payment)
                {
                    /* 原始資料 */
                    outputStream.write(lineBytes);
                    
                    /* 繳費單狀態 */
                    outputStream.write(getWriteData(payment.getPaymentStatus().toString() , "S", 1));
                    String statusName = CodeTableUtil.getInstance().getCodeName(CodeTableUtil.CODE_KIND_PAYMENT_STATUS, payment.getPaymentStatus().toString());
                    outputStream.write(getWriteData(statusName , "S", 20));

                    /* 已繳款加入繳款日期時間, 繳款通路代碼, 繳款通路說明, 實際繳款金額(2011/09/07 YD) */
                    if(payment.getPaymentStatus().equals(new Integer(5)))  
                    {
                        String channel = "";
                        outputStream.write(getWriteData(objectToString(payment.getWriteOffPayment().getWriteOffDate()) , "S", 14));

                        outputStream.write(getWriteData(objectToString(payment.getWriteOffPayment().getChannel()) ,"S", 1));

                        channel = CodeTableUtil.getInstance().getCodeName(CodeTableUtil.CODE_KIND_CHANNEL, payment.getWriteOffPayment().getChannel());
                        outputStream.write(getWriteData(objectToString(channel) ,"S",  20));
                        
                        /* 增加實際繳款金額(2011/09/07 YD) */
                        if (payment.getRealPayAmount() == null){
                        	logger.error("{} 已繳款，但實繳金額為null..", virtualAccount);
                        	outputStream.write(getWriteData(objectToString("") ,"S",  7));
                        }else{	
                            outputStream.write(getWriteData(objectToString(payment.getRealPayAmount()) ,"", 7));
                        }    
                    }
                    else
                    {
                        outputStream.write(getWriteData("" , "S", 35));
                    }
                    
                    outputStream.write("\r\n".getBytes());
                }
                
            }

            outputStream.flush();
            outputStream.close();
            outputStream = null;

            reader.close();
            reader = null;

            byte[] bytes = new byte[(int)file.length()];

            BufferedInputStream bufferedInputStream = 
                new BufferedInputStream(new FileInputStream(file)); 

            bufferedInputStream.read(bytes);

            ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
            inputStream.close();
            bufferedInputStream.close();

            /* 下載檔名 */
            
            
            String   fname= uploadFile.getFileName();             
            int   sub  =fname.indexOf(".");                      
            if(0 > sub){
                
                fileName = fname + "_R.txt"; 
                
            }else{
            
                 fileName = uploadFile.getFileName().substring(0, sub) + "_R.txt";  
             
            }            
                      
            String isoFileName = new String(fileName.getBytes(), "ISO8859-1");

            streamingResolution = new StreamingResolution( 
                            "application/pdf",inputStream).setFilename(isoFileName);

        } 
        catch (Exception e) 
        {
            logger.error("帳單明細下載錯誤(Soez1018ActionBean.doDownloadUploadFileAction):", e);

            // 轉換錯誤訊息
            ValidationErrors errors = new ValidationErrors();
            errors.addGlobalError(new LocalizableError("doDownloadUploadFileAction.exception") );
            getContext().setValidationErrors(errors);
            // 回傳 錯誤 HTML fragments
            return super.errorsToHtmlStreams(errors);
        }
        finally
        {
            
            try {
                if (null != outputStream)
                    outputStream.close();
            }
            catch (IOException e) {
            }
            outputStream = null;
            
            try {
                if (null != reader)
                    reader.close();
            }
            catch (IOException e) {
            }
            reader = null;
        }

        return streamingResolution;
    }

    private Payment getPayment(List<Payment> payments, String virtualAccount)
    {
        for (int i=0; i < payments.size(); i++)
        {
            Payment payment = payments.get(i);
            if (payment.getVirtualAccount().equals(virtualAccount)){
                payments.remove(i);                
                return payment;
            }
        }

        return null;
    }

    public String objectToString(Object object)
    {
        String result = null;
        if(object != null)
        {
            if(object.getClass().equals(String.class))
            {
                result = (String)object;
            }else if(object.getClass().equals(Long.class))
            {
                result = String.valueOf(object);
            }else if(object.getClass().equals(Timestamp.class))
            {
                Date date = (Date)object;
                result = dateFormat.format(date);
            }
        }
        return result;
    }

    public byte[] getWriteData(String context , String type, Integer len)
    {
        byte[] result = new byte[len.intValue()];
        if(type.equals("S"))
        {
            for(int i=0;i<len.intValue();i++)
            {
                result[i] = 0x20;
            }
            if(context != null && !"".equals(context))
            {
                /*
                 * 判斷字串是否比設定的長度還長,
                 * 若是, 則把多的字串去除
                 */
                try {
                    if(context.getBytes().length > len.intValue())
                    {

                        System.arraycopy(
                                        context.getBytes("MS950"), 0, result, 0, len.intValue());
                    }else
                    {
                        System.arraycopy(
                                        context.getBytes("MS950"), 0, result, 0, context.getBytes("MS950").length);
                    }
                } catch (Exception e) {
                    logger.error("轉碼失敗:", e);
                }
            }
        }else
        {
            for(int i=0;i<len.intValue();i++)
            {
                result[i] = '0';
            }
            if(context != null && !"".equals(context))
            {
                if(Long.valueOf(context).intValue() >= 0)
                {
                    result[0] = '+';
                }else
                {
                    result[0] = '-';
                    context = String.valueOf(0 - Long.valueOf(context).intValue());
                }
                try {
                    System.arraycopy(
                                    context.getBytes(), 0, result, 
                                    len.intValue()-context.getBytes("MS950").length, context.getBytes().length);
                } catch (Exception e) {
                    logger.error("轉碼失敗:", e);
                }

            }
        }

        return result;
    }


    public Resolution doAjaxGroupNoChange()
    {
        return new ForwardResolution(AJAX_FORMT_DEF_OPTIONS_JSP);
    }


    public List<QryDownloadFileList> getQueryResult() {
        return queryResult;
    }



    public void setQueryResult(List<QryDownloadFileList> queryResult) {
        this.queryResult = queryResult;
    }
    public Payment getResultPayment() {
        return resultPayment;
    }



    public void setResultPayment(Payment resultPayment) {
        this.resultPayment = resultPayment;
    }


    public Long getUploadFilePk() {
        return uploadFilePk;
    }



    public void setUploadFilePk(Long uploadFilePk) {
        this.uploadFilePk = uploadFilePk;
    }



    public UploadFile getQryUploadFile() {
        return qryUploadFile;
    }



    public void setQryUploadFile(UploadFile qryUploadFile) {
        this.qryUploadFile = qryUploadFile;
    }



    public Group getGroup() {
        return group;
    }



    public void setGroup(Group group) {
        this.group = group;
    }

    public Group getQryGroup() {
        return qryGroup;
    }



    public void setQryGroup(Group qryGroup) {
        this.qryGroup = qryGroup;
    }



    public PaginatedList<Group> getQueryGroupResult() {
        return queryGroupResult;
    }



    public void setQueryGroupResult(PaginatedList<Group> queryGroupResult) {
        this.queryGroupResult = queryGroupResult;
    }


    public PaginatedList<Payment> getQueryPaymentResult() {
        return queryPaymentResult;
    }



    public void setQueryPaymentResult(PaginatedList<Payment> queryPaymentResult) {
        this.queryPaymentResult = queryPaymentResult;
    }


    /**
     * @return the qryUploadFrom
     */
    public Date getQryUploadFrom() {
        return qryUploadFrom;
    }


    /**
     * @param qryUploadFrom the qryUploadFrom to set
     */
    public void setQryUploadFrom(Date qryUploadFrom) {
        this.qryUploadFrom = qryUploadFrom;
    }


    /**
     * @return the qryUploadTo
     */
    public Date getQryUploadTo() {
        return qryUploadTo;
    }


    /**
     * @param qryUploadTo the qryUploadTo to set
     */
    public void setQryUploadTo(Date qryUploadTo) {
        this.qryUploadTo = qryUploadTo;
    }

    /**
     * @return the formatDefinitionoOptions
     */
    public List<LabelValue> getFormatDefinitionoOptions() {
        if (null == this.formatDefinitionoOptions)
        {
            //如果不是銀行端，則查詢條件要加入帳單業者限制
            if (!UserUtil.isBankGroup())
            {
                // 查詢條件
                FormatDefinition formatDefinition = new FormatDefinition();
                Group group = new Group();
                group.setGroupPk(UserUtil.getUserGroup().getGroupPk());
                formatDefinition.setGroup(group);
                formatDefinition.setFormatType(new Integer(1));
                formatDefinition.setDeleted(Boolean.FALSE);
                formatDefinitionoOptions = formatDefinitionService.findLabelValueByFormatDefinition(formatDefinition, true);
            }
            else
            {
                // 銀行端，看是否有群組代碼，若沒有則回傳空陣列
                if (null != this.getQryUploadFile() && null != this.getQryUploadFile().getGroup())
                {
                    // 查詢條件
                    FormatDefinition formatDefinition = new FormatDefinition();
                    formatDefinition.setGroup(this.getQryUploadFile().getGroup());
                    formatDefinition.setFormatType(new Integer(1));
                    formatDefinition.setDeleted(Boolean.FALSE);
                    formatDefinitionoOptions = formatDefinitionService.findLabelValueByFormatDefinition(formatDefinition, true);
                }
                else
                {
                    this.formatDefinitionoOptions = new ArrayList<LabelValue>();                    
                }

            }

        }
        else
        {
            // do nothing.
        }
        return formatDefinitionoOptions;
    }


    /**
     * @param formatDefinitionoOptions the formatDefinitionoOptions to set
     */
    public void setFormatDefinitionoOptions(List<LabelValue> formatDefinitionoOptions) {
        this.formatDefinitionoOptions = formatDefinitionoOptions;
    }

    public PaymentService getPaymentService() {
        return paymentService;
    }

    public void setPaymentService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public Integer getQryPaymentStatus() {
        return qryPaymentStatus;
    }

    public void setQryPaymentStatus(Integer qryPaymentStatus) {
        this.qryPaymentStatus = qryPaymentStatus;
    }

}
